#include "LifeGameScene.h"
#include "SimpleAudioEngine.h"

USING_NS_CC;

Scene* LifeGame::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();
    
    // 'layer' is an autorelease object
    auto layer = LifeGame::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool LifeGame::init()
{
    if ( !Layer::init() )
    {
        return false;
    }

	auto listener = EventListenerTouchOneByOne::create();
	listener->setSwallowTouches(true);
	listener->onTouchBegan = [](Touch* touch, Event* event) {
		auto target = static_cast<cocos2d::LayerColor*>(event->getCurrentTarget());
		Point locationInNode = target->convertToNodeSpace(touch->getLocation());
		Size s = target->getContentSize();
		Rect rect = Rect(0, 0, s.width, s.height);

		if (rect.containsPoint(locationInNode))
		{
			log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);
			if (target->getColor() == Color3B::BLACK) {
				target->setColor(Color3B::GRAY);
			}
			else {
				target->setColor(Color3B::BLACK);
			}
			int tag = target->getTag();
			log("row = %d, col = %d", tag >> 8, tag & 0xFF);
			return true;
		}
		return false;
	};
    
    auto visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

	float squareSize = calculateSquareSize(visibleSize.width, visibleSize.height);

	Vec2 firstSquarePosition = Vec2(visibleSize.width / (NUM_SQUARE + NUM_PADDING_SQUARE) + origin.x,
		visibleSize.height / (NUM_SQUARE + NUM_PADDING_SQUARE) + origin.y);

	// create square grid
	float rowPosition = firstSquarePosition.y;
	float colPosition = 0.0f;

	for (int row = 0; row < NUM_SQUARE; ++row) {
		rowPosition = rowPosition  + 10.0f + squareSize;

		colPosition = firstSquarePosition.x;
		for (int col = 0; col < NUM_SQUARE; ++col) {
			colPosition = colPosition  + 10.0f + squareSize;

			auto layer = cocos2d::LayerColor::create(Color4B::GRAY);

			layer->setContentSize(CCSizeMake(squareSize, squareSize));
			layer->ignoreAnchorPointForPosition(false);
			layer->setPosition(Vec2(rowPosition, colPosition));
			layer->setTag(row << 8 | col);

			mSquareMatrix[row][col] = layer;

			this->addChild(layer, 1);

			if (row == 0 && col == 0) {
				_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, layer);
			}
			else {
				_eventDispatcher->addEventListenerWithSceneGraphPriority(listener->clone(), layer);
			}
			
		}
	}

	auto start = MenuItemFont::create("Start", CC_CALLBACK_1(LifeGame::startMenuCallback, this));
	start->setFontName("Marker Felt");
	start->setColor(Color3B::BLACK);
	start->setPosition(Vec2::ZERO);
	auto reset = MenuItemFont::create("Reset", CC_CALLBACK_1(LifeGame::resetMenuCallback, this));
	reset->setFontName("Marker Felt");
	reset->setColor(Color3B::BLACK);
	reset->setPosition(Vec2(0.0f, -50.0f));
	auto menu = Menu::create(start, reset, NULL);
	menu->ignoreAnchorPointForPosition(true);
	menu->setPosition(Vec2(rowPosition + squareSize + 80.0f, colPosition));
	this->addChild(menu);

    return true;
}

float LifeGame::calculateSquareSize(float width, float height)
{
	float l = width > height ? width : height;

	return l / (float)(NUM_SQUARE + NUM_PADDING_SQUARE);
}

void LifeGame::startMenuCallback(Ref* pSender)
{
	auto label = Label::createWithSystemFont("Begin evolve!", "Marker Felt", 25);
	label->setColor(Color3B::BLACK);
	auto visibleSize = Director::getInstance()->getVisibleSize();
	Vec2 origin = Director::getInstance()->getVisibleOrigin();
	label->setPosition(Vec2(visibleSize.width / 2.0f + origin.x, visibleSize.height / 2.0f + origin.y));
	this->addChild(label, 2, START_TAG);

	scheduleOnce(schedule_selector(LifeGame::closeLabel), 1);

	schedule(schedule_selector(LifeGame::calcuate), 1);
}

void LifeGame::resetMenuCallback(Ref* pSender)
{
	unschedule(schedule_selector(LifeGame::calcuate));

	closeLabel(0.0f);

	for (int row = 0; row < NUM_SQUARE; ++row) {
		for (int col = 0; col < NUM_SQUARE; ++col) {
			mSquareMatrix[row][col]->setColor(Color3B::GRAY);
		}
	}
}

void LifeGame::calcuate(float dt)
{
	int numBlackSqure = 0;
	int changeTime = 0;

	for (int row = 0; row < NUM_SQUARE; ++row) {
		for (int col = 0; col < NUM_SQUARE; ++col) {
			numBlackSqure = 0;

			if (mSquareMatrix[row][col]->getColor() == Color3B::BLACK) {

				numBlackSqure = this->getBlackSqure(row, col);
				if (numBlackSqure < 2) {
					// Die
					++changeTime;
					mSquareMatrix[row][col]->setTag(mSquareMatrix[row][col]->getTag() | DIE_FLAG);
				}
			}
			else {
				numBlackSqure = this->getBlackSqure(row, col);
				if (numBlackSqure >= 3) {
					// Resurrection
					++changeTime;
					mSquareMatrix[row][col]->setTag(mSquareMatrix[row][col]->getTag() | NEW_FLAG);
				}
			}
		}
	}

	for (int row = 0; row < NUM_SQUARE; ++row) {
		for (int col = 0; col < NUM_SQUARE; ++col) {
			if (mSquareMatrix[row][col]->getTag() & DIE_FLAG) {
				mSquareMatrix[row][col]->setColor(Color3B::GRAY);

				mSquareMatrix[row][col]->setTag(mSquareMatrix[row][col]->getTag() ^ DIE_FLAG);
			}
			else if (mSquareMatrix[row][col]->getTag() & NEW_FLAG) {
				mSquareMatrix[row][col]->setColor(Color3B::BLACK);

				mSquareMatrix[row][col]->setTag(mSquareMatrix[row][col]->getTag() ^ NEW_FLAG);
			}
		}
	}

	if (changeTime == 0) {
		unschedule(schedule_selector(LifeGame::calcuate));

		auto label = Label::createWithSystemFont("Evolve finished!", "Marker Felt", 25);
		label->setColor(Color3B::RED);
		auto visibleSize = Director::getInstance()->getVisibleSize();
		Vec2 origin = Director::getInstance()->getVisibleOrigin();
		label->setPosition(Vec2(visibleSize.width / 2.0f + origin.x, visibleSize.height / 2.0f + origin.y));
		this->addChild(label, 2, START_TAG);
		
		scheduleOnce(schedule_selector(LifeGame::closeLabel), 1);
	}
}

int LifeGame::getBlackSqure(int i, int j)
{
	int numBlackSqure = 0;

	if((i + 1 < NUM_SQUARE) && (mSquareMatrix[i + 1][j]->getColor() == Color3B::BLACK)){
		++numBlackSqure;
	}
	if ((j + 1 < NUM_SQUARE) && (mSquareMatrix[i][j + 1]->getColor() == Color3B::BLACK)) {
		++numBlackSqure;
	}
	if ((i - 1 >= 0) && (mSquareMatrix[i - 1][j]->getColor() == Color3B::BLACK)) {
		++numBlackSqure;
	}
	if ((j - 1 >= 0) && (mSquareMatrix[i][j - 1]->getColor() == Color3B::BLACK)) {
		++numBlackSqure;
	}
	if ((i + 1 < NUM_SQUARE) && (j + 1 < NUM_SQUARE) && (mSquareMatrix[i + 1][j + 1]->getColor() == Color3B::BLACK)) {
		++numBlackSqure;
	}
	if ((i - 1 >= 0) && (j - 1 >= 0) && (mSquareMatrix[i - 1][j - 1]->getColor() == Color3B::BLACK)) {
		++numBlackSqure;
	}
	if ((i + 1 < NUM_SQUARE) && (j - 1 >= 0) && (mSquareMatrix[i + 1][j - 1]->getColor() == Color3B::BLACK)) {
		++numBlackSqure;
	}
	if ((i - 1 >= 0) && (j + 1 < NUM_SQUARE) && (mSquareMatrix[i - 1][j + 1]->getColor() == Color3B::BLACK)) {
		++numBlackSqure;
	}

	return numBlackSqure;
}

void LifeGame::closeLabel(float dt)
{
	auto label = this->getChildByTag(START_TAG);
	if(label){
		this->removeChildByTag(START_TAG);
	}

	label = this->getChildByTag(END_TAG);
	if (label){
		this->removeChildByTag(END_TAG);
	}
}

void LifeGame::menuCloseCallback(Ref* pSender)
{
    //Close the cocos2d-x game scene and quit the application
    Director::getInstance()->end();

    #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
    
    /*To navigate back to native iOS screen(if present) without quitting the application  ,do not use Director::getInstance()->end() and exit(0) as given above,instead trigger a custom event created in RootViewController.mm as below*/
    
    //EventCustom customEndEvent("game_scene_close_event");
    //_eventDispatcher->dispatchEvent(&customEndEvent);
    
    
}
